package org.django4j;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class WebControllerInvoker implements ControllerInvoker {
    private final Log logger = LogFactory.getLog(WebControllerInvoker.class);
    
    /**
     * @see ControllerInvoker#invoke(HttpServletRequest, HttpServletResponse, Object, Method, Object[])
     */
    public Model invoke(HttpServletRequest request,
            HttpServletResponse response, Object controller, Method method,
            Object[] args) {
        if (controller == null || method == null || args == null){
            throw new IllegalArgumentException("None of (controller, method, args) can be null.");
        }
        Class clazz = controller.getClass();
        int expectCount = method.getParameterTypes().length; 
        if (expectCount != args.length + 2){
            // 检验是否传入的参数个数和方法声明中参数的个数相等，传入的参数不包括(request,response)
            throw new Django4jException(clazz.getName()+ ":" + method.getName() 
                    + " exptect " + expectCount + " parameters, but " + args.length);
        }
        
        Object expectArgs[] = new Object[expectCount];
        expectArgs[0] = request;
        expectArgs[1] = response;
        System.arraycopy(args, 0, expectArgs, 2, args.length);
        
        if (logger.isDebugEnabled()){
            logger.debug("Ready to invoke " + clazz.getName() + "." + method.getName() 
                    + "(" + getArgsString(expectArgs) + ").");
        }
        
        try{
            // do actually invocation of controller
            return (Model)method.invoke(controller, expectArgs);
        }
        catch(Exception e){
            throw new Django4jException(e);
        }
    }
    
    private String getArgsString(Object args[]){
        StringBuffer buffer = new StringBuffer();
        for (Object arg : args){
            buffer.append(arg).append(", ");
        }
        return buffer.toString();
    }
}
